﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;

namespace DataAccess
{
    public class ControllerPersona
    {
        #region ATRIBUTOS

        private SqlConnection conexion = DBConnection.getInstancia().getConnection();

        private static ControllerPersona unConPer;

        #endregion
        
        #region SINGLETON

        public static ControllerPersona getInstancia()
        {
            if(unConPer == null)
            {
                unConPer = new ControllerPersona();
            }
            return unConPer;
        }

        #endregion

        #region CONSTRUCTORES

        private ControllerPersona()
        {}

        #endregion

        #region METODOS

        //Actualizar datos de Persona.
        public void updatePersona(Int32 pNro, string pNom, string pAp, string pTel, string pInt, string pMail, string pSec, string pCont)
        {
            try
            {
                //Sentencia sql.
                string sql = "UPDATE personas SET pernombre=@pNom, perapellido=@pAp, pertelefono=@pTel, perinterno=@pInt, perseccion=@pSec, permail=@pMail, percontrasenia=@pCont WHERE pernrofuncionario=@pNro;";
                 //Se crea el comando.
                SqlCommand myComm = new SqlCommand(sql, conexion);
                myComm.Parameters.AddWithValue("pNro", pNro);
                myComm.Parameters.AddWithValue("pNom", truncar(pNom, 29));
                myComm.Parameters.AddWithValue("pAp", truncar(pAp, 29));
                myComm.Parameters.AddWithValue("pTel", truncar(pTel, 29));
                myComm.Parameters.AddWithValue("pInt", truncar(pInt, 19));
                myComm.Parameters.AddWithValue("pMail", truncar(pMail, 49));
                myComm.Parameters.AddWithValue("pSec", truncar(pSec, 49));
                myComm.Parameters.AddWithValue("pCont", truncar(pCont, 19));
                
                //Se abre la conexion.
                conexion.Open();
                //Se ejecuta el comando.
                int x = myComm.ExecuteNonQuery();

                if(x == 0)
                {
                    throw new Exception("Error al modificar el funcionario");
                }
            }catch(Exception ex)
            {
                throw new Exception("Error al modificar el funcionario " + ex.Message);
            }
            finally
            {
                //Cerramos la conexion.
                conexion.Close();
            }
            


        }
        //Cambia el estado de un funcionario, (le da baja logica o lo activa, segun el valor del parametro pEstado).

        public void cambiarEstadoFuncionario(Int32 pNro, bool pEstado)
        {
            try
            {
                //Sentencia sql.
                string sql = "UPDATE personas SET peractivo=@pEst WHERE pernrofuncionario=@pNro;";
                //Se crea el comando.
                SqlCommand myComm = new SqlCommand(sql, conexion);
                myComm.Parameters.AddWithValue("pEst", pEstado ? 1 : 0);
                myComm.Parameters.AddWithValue("pNro", pNro);
                //Se abre la conexion.
                conexion.Open();
                //Se ejecuta el comando.
                int x = myComm.ExecuteNonQuery();

                if (x == 0)
                {
                    throw new Exception("Error al cambiar el estado del funcionario");
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error al cambiar el estado delfuncionario " + ex.Message);
            }
            finally
            {
                //Cerramos la conexion.
                conexion.Close();
            }
        }
        //public void deleteFuncionario(Int32 pNro, string pTabla, string pCampoNro)
        //{
        //    try
        //    {
        //        //Se abre la conexion. 
        //        conexion.Open();
        //        //Se declara la transaccion.
        //        SqlTransaction myTrans = conexion.BeginTransaction(IsolationLevel.Serializable);
        //        //Se crea el comando.
        //        SqlCommand myComm = conexion.CreateCommand();
        //        //Se le asigna la transaccion a la propiedad Transaction del comando creado.
        //        myComm.Transaction = myTrans;
        //        try
        //        {
        //            //Se elimina el funcionario de la tabla especifica.
        //            myComm.CommandText = "DELETE FROM " + pTabla + " WHERE " + pCampoNro + "=" + pNro + ";";
        //            //Ejecutamos el comando.
        //            myComm.ExecuteNonQuery();
        //            //Se da baja logica al funcionario de la tabla "personas", cambiando su estado a "inactivo" (0).
        //            myComm.CommandText = "UPDATE personas SET peractivo=0 WHERE pernrofuncionario=" + pNro + ";";
        //            //Se ejecuta el comando.
        //            myComm.ExecuteNonQuery();
        //            //Hacemos el commit.
        //            myTrans.Commit();
        //        }
        //        catch (SqlException e)
        //        {
        //            try
        //            {
        //                //Se hace el rollback.
        //                myTrans.Rollback();

        //            }
        //            catch (SqlException ex)
        //            {
        //                throw ex;
        //            }
        //        }

        //    }
        //    catch (SqlException ex)
        //    {
        //        throw ex;
        //    }
        //    finally
        //    {
        //        //Se cierra la conexion.
        //        conexion.Close();
        //    }
        //}

        //Dar Nro. por Nro y Contraseña de funcionario.
        public Int32 getIdFuncByNroAndCont(Int32 pNroFunc, string pCont, bool pEstado)
        {
            //Recibe el Numero de funcionario la contraseña y el estado (activo o no), y devuelve el Nro de funcionario a quien corresponden, si existe.
            Int32 perId = -1;
            try
            {
                //Consulta.
                string sql = "SELECT pernrofuncionario FROM personas WHERE pernrofuncionario = @pernrofunc AND percontrasenia = @percontrasenia AND peractivo = @peractivo;";
                //Se crea el comando
                SqlCommand comm = new SqlCommand(sql, conexion);
                comm.Parameters.AddWithValue("pernrofunc", pNroFunc);
                comm.Parameters.AddWithValue("percontrasenia", pCont);
                comm.Parameters.AddWithValue("peractivo", Convert.ToInt16(pEstado));
                //Se abre la conexion.
                conexion.Open();
                perId = (comm.ExecuteScalar() != null) ? int.Parse(comm.ExecuteScalar().ToString()) : -1;

            }
            catch(Exception ex)
            {
                throw new Exception("Error al buscar el funcionario por Nro y Contraseña: " + ex.Message);
            }
            finally
            {
                //Se cierra la conexion.
                conexion.Close();
            }
            //Se devuelve el numero de funcionario.
            return perId;
        }

        //Verificar y dar rol del funcionario por Mail y Contraseña.
        //public string verificarFuncionario(Int32 pNro, string pCont)
        //{
        //    string rol = "";
        //    //Se consigue el Nro de funcionario correspondiente al Nro y contraseña recibidos.
        //    Int32 nro = getIdFuncByNroAndCont(pNro, pCont, true);
        //    if (nro > 0)
        //    {
        //        //Se busca el nro de funcionario en las distintas tablas de roles especificos (Administrador, Supervisor, Tecnico o Usuario), hasta
        //        //encontrar el que corresponde al funcionario.
        //        if (ControllerAdministrador.getInstancia().getAdministradorByNro(nro).Rows.Count != 0)
        //        {
        //            rol = "Administrador";
        //        }
        //        else if (ControllerSupervisor.getInstancia().getSupervisorByNro(nro).Rows.Count != 0)
        //        {
        //            rol = "Supervisor";
        //        }
        //        else if (ControllerTecnico.getInstancia().getTecnicoByNro(nro).Rows.Count != 0)
        //        {
        //            rol = "Tecnico";
        //        }
        //        else if (ControllerUsuario.getInstancia().getUsuarioByNro(nro).Rows.Count != 0)
        //        {
        //            rol = "Usuario";
        //        }
        //    }
        //    //Se retorna el rol del funcionario
        //    return rol;
        //}
        public DataTable getFuncionarioByNro(Int32 pNro, string pTabla, string pCampoNro)
        {
            //Consulta.
            string sql = "SELECT * FROM personas WHERE pernrofuncionario=" + pNro + " AND " + pNro + " IN(SELECT " + pCampoNro + " FROM " + pTabla + ");";
            //Se crea el datatable.
            DataTable myDt = new DataTable();
            //Se crea el comando.
            SqlCommand myComm = new SqlCommand(sql, conexion);
            //Se crea el data adapter para llenar la tabla y se le pasa el comando como parametro.
            SqlDataAdapter myDa = new SqlDataAdapter(myComm);
            try
            {
                //Se abre la conexion.
                conexion.Open();
                //Se llena la tabla con el data adapter.
                myDa.Fill(myDt);
            }
            catch (SqlException ex)
            {
                throw ex;
            }
            finally
            {
                //Se cierra la conexion.
                conexion.Close();
            }
            //Se devuelve el data table.
            return myDt;
        }

        //Dar Persona por Nombre de funcionario.
        public DataTable getFuncionarioByName(string pNom,string pAp, string pTabla, string pCampoNro)
        {
            //Consulta.
            string sql = "SELECT * FROM personas WHERE pernombre='" + pNom + "' AND perapellido='" + pAp + "' AND pernrofuncionario IN(SELECT " + pCampoNro + " FROM " + pTabla + ");";
            //Se crea el datatable.
            DataTable myDt = new DataTable();
            //Se crea el comando.
            SqlCommand myComm = new SqlCommand(sql, conexion);
            //Se crea el data adapter para llenar la tabla y se le pasa el comando como parametro.
            SqlDataAdapter myDa = new SqlDataAdapter(myComm);
            try
            {
                //Se abre la conexion.
                conexion.Open();
                //Se llena la tabla con el data adapter.
                myDa.Fill(myDt);
            }
            catch (SqlException ex)
            {
                throw ex;
            }
            finally
            {
                //Se cierra la conexion.
                conexion.Close();
            }
            //Se devuelve el data table.
            return myDt;
        }

        //Dar funcionarios por estado.
        public DataTable getFuncionariosActivos(bool pEstado, string pCampoNro, string pTabla)
        {
            //Recibe el estado del funcionario, el campo de la tabla y la tabla del funcionario especializado.
            //Consulta.
            string sql = "SELECT * FROM personas WHERE perestado=" + pEstado + " AND pernrofuncionario IN(SELECT " + pCampoNro + " FROM " + pTabla + ");";
            //Se crea el datatable.
            DataTable myDt = new DataTable();
            //Se crea el comando.
            SqlCommand myComm = new SqlCommand(sql, conexion);
            //Se crea el data adapter para llenar la tabla y se le pasa el comando como parametro.
            SqlDataAdapter myDa = new SqlDataAdapter(myComm);
            try
            {
                //Se abre la conexion.
                conexion.Open();
                //Se llena la tabla con el data adapter.
                myDa.Fill(myDt);
            }
            catch (SqlException ex)
            {
                throw ex;
            }
            finally
            {
                //Se cierra la conexion.
                conexion.Close();
            }
            //Se devuelve el data table.
            return myDt;
        }

        //Dar todos los funcionarios por estado y con formato. Es para ser usada en THD Escritorio.
        public DataTable getFuncionariosByEstado(bool pEstado)
        {
            //Recibe el estado del funcionario, el campo de la tabla y la tabla del funcionario especializado.
            //Consulta.
            string sql = "(SELECT p.pernrofuncionario AS Funcionario, CONCAT(p.pernombre,' ',p.perapellido) AS Nombre, p.pertelefono AS Telefono, p.perinterno AS Interno, p.permail AS eMail, p.perseccion AS Seccion, 'Usuario' AS Rol FROM personas AS p WHERE p.peractivo=@pEst AND p.pernrofuncionario in (SELECT usunrofuncionario FROM usuarios)) UNION (SELECT p.pernrofuncionario AS Funcionario, CONCAT(p.pernombre,' ',p.perapellido) AS Nombre, p.pertelefono AS Telefono, p.perinterno AS Interno, p.permail AS eMail, p.perseccion AS Seccion, 'Administrador' AS Rol FROM personas AS p WHERE p.peractivo=@pEst AND p.pernrofuncionario in (SELECT admnrofuncionario FROM administradores)) UNION (SELECT p.pernrofuncionario AS Funcionario, CONCAT(p.pernombre,' ',p.perapellido) AS Nombre, p.pertelefono AS Telefono, p.perinterno AS Interno, p.permail AS eMail, p.perseccion AS Seccion, 'Tecnico' AS Rol FROM personas AS p WHERE p.peractivo=@pEst AND p.pernrofuncionario in (SELECT tecnrofuncionario FROM tecnicos)) UNION (SELECT p.pernrofuncionario AS Funcionario, CONCAT(p.pernombre,' ',p.perapellido) AS Nombre, p.pertelefono AS Telefono, p.perinterno AS Interno, p.permail AS eMail, p.perseccion AS Seccion, 'Supervisor' AS Rol FROM personas AS p WHERE p.peractivo = @pEst AND p.pernrofuncionario in (SELECT supnrofuncionario FROM supervisores));";
            //Se crea el datatable.
            DataTable myDt = new DataTable();
            //Se crea el comando.
            SqlCommand myComm = new SqlCommand(sql, conexion);
            myComm.Parameters.AddWithValue("pEst", pEstado ? 1 : 0);
            //Se crea el data adapter para llenar la tabla y se le pasa el comando como parametro.
            SqlDataAdapter myDa = new SqlDataAdapter(myComm);
            try
            {
                //Se abre la conexion.
                conexion.Open();
                //Se llena la tabla con el data adapter.
                myDa.Fill(myDt);
            }
            catch (SqlException ex)
            {
                throw ex;
            }
            finally
            {
                //Se cierra la conexion.
                conexion.Close();
            }
            //Se devuelve el data table.
            return myDt;
        }
        string truncar(string unSt, int maxLength)
        {
            return unSt.Length <= maxLength ? unSt : unSt.Substring(0, maxLength);
        } 
        #endregion
    }
}
